package com.jysz.certificate.service.pm;

import java.util.Iterator;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;
import javax.persistence.criteria.JoinType;

import org.hibernate.Criteria;
import org.hibernate.SQLQuery;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Projections;
import org.hibernate.criterion.Restrictions;
import org.hibernate.sql.JoinFragment;
import org.springframework.stereotype.Service;

import com.jysz.certificate.Constants;
import com.jysz.certificate.persistence.dao.pm.PAShopMonthDetailDao;
import com.jysz.certificate.persistence.enums.PostType;
import com.jysz.certificate.persistence.model.pm.AssignUser;
import com.jysz.certificate.persistence.model.pm.PAShopMonthDetail;
import com.jysz.certificate.persistence.model.pm.PerformanceAssign;
import com.jysz.certificate.persistence.model.pm.PerformanceAssignShopDetail;
import com.jysz.certificate.persistence.model.system.Financial;
import com.jysz.certificate.persistence.model.system.User;
import com.jysz.certificate.service.mf.BillOptionService;
import com.jysz.webcore.ssh.service.EntityService;
import com.jysz.webcore.utils.ReflectionUtils;

/**
 * @author <a href="mailto:javaengine@outlook.com">Kaca Rich</a>
 *
 */
@Service
public class PAShopMonthDetailService extends EntityService<PAShopMonthDetail, Long, PAShopMonthDetailDao>{

	@Resource
	private PAShopMonthDetailDao paShopMonthDetailDao;
	@Resource
	private AssignUserService assignUserService;
	@Resource
	private PerformanceAssignShopDetailService pmAssignShopDetailService;
	@Resource
	private PerformanceAssignService performanceAssignService;
	@Resource
	private BillOptionService billOptionService;
	
	@Override
	public PAShopMonthDetailDao getEntityDao() {
		return paShopMonthDetailDao;
	}

	public List<PAShopMonthDetail> findByShopDetail(
			PerformanceAssignShopDetail entity) {
		return this.getEntityDao().findByShopDetail(entity);
	}

	/**
	 * @param monthDetail
	 * @param map
	 * @param areaTotalAmount 
	 */
	public void saveShopMonthDetail(PAShopMonthDetail monthDetail,
			Map<Long, AssignUser> map, double areaTotalAmount, User user) {
		List<AssignUser> assignUsers = monthDetail.getAssignUsers();
		
		
		double amount = 0;
		if(assignUsers != null && assignUsers.size() > 0){
			for (Iterator<AssignUser> iterator = assignUsers.iterator(); iterator.hasNext();) {
				AssignUser assignUser = iterator.next();
				AssignUser assignUserValue = map.get(assignUser.getId());
				
				if(assignUser.getAmount() != assignUserValue.getAmount()){
					if(PostType.Manager.equals(user.getPost())){
						assignUser.setDisplayColor(Constants.COLOR_RED);
					}else{
						if(PostType.Manager.equals(assignUser.getLastUpdatePost())){
							assignUser.setDisplayColor(Constants.COLOR_YELLOW);
						}
					}
					assignUser.setLastUpdatePost(user.getPost());
				}
				
				assignUser.setAmount(assignUserValue.getAmount());
				assignUser.setRemark(assignUserValue.getRemark());
				amount += assignUser.getAmount();
				assignUserService.save(assignUser);
			}
			
		}
		
		//更新区域经理绩效
		double oldAreaTotalAmount = monthDetail.getPerformanceAssignShopDetail().getAreaTotalAmount();
		monthDetail.getPerformanceAssignShopDetail().setAreaTotalAmount(oldAreaTotalAmount - monthDetail.getAreaTotalAmount() + areaTotalAmount);
		monthDetail.setAreaTotalAmount(areaTotalAmount);
		
		monthDetail.getPerformanceAssignShopDetail().getPerformanceAssign()
				.setAreaTotalAmount(monthDetail.getPerformanceAssignShopDetail().
						getPerformanceAssign().getAreaTotalAmount() - oldAreaTotalAmount
						+ monthDetail.getPerformanceAssignShopDetail().getAreaTotalAmount());
		
		this.updateUpTotalAmount(monthDetail, amount);
		
	}

	/**
	 * 更新相关总计
	 * @param monthDetail
	 * @param amount
	 */
	public void updateUpTotalAmount(PAShopMonthDetail monthDetail,
			double newAmount) {
		double totalAmount = monthDetail.getTotalAmount();//旧的金额
		
		monthDetail.setTotalAmount(newAmount);
		this.save(monthDetail);
		
		newAmount = monthDetail.getPerformanceAssignShopDetail().getTotalAmount() - totalAmount + monthDetail.getTotalAmount();
		totalAmount = monthDetail.getPerformanceAssignShopDetail().getTotalAmount();
		
		monthDetail.getPerformanceAssignShopDetail().setTotalAmount(newAmount);
		
		newAmount = monthDetail.getPerformanceAssignShopDetail().getPerformanceAssign().getTotalAmount() - totalAmount + monthDetail.getPerformanceAssignShopDetail().getTotalAmount();
		
		monthDetail.getPerformanceAssignShopDetail().getPerformanceAssign().setTotalAmount(newAmount);
		
		this.save(monthDetail);
		pmAssignShopDetailService.save(monthDetail.getPerformanceAssignShopDetail());
		performanceAssignService.save(monthDetail.getPerformanceAssignShopDetail().getPerformanceAssign());
	}

	@SuppressWarnings("unchecked")
	public List<PAShopMonthDetail> findByPerformanceAssign(
			PerformanceAssign entity) {
		
		Criteria criteria = this.getEntityDao().createCriteria();
		criteria.createCriteria("performanceAssignShopDetail").add(Restrictions.eq("performanceAssign", entity));
		
		return criteria.list();
	} 
	
	/**
	 * 查找这次绩效所关联的金融机构,按月份 收
	 * 
	 * @param entity
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public List<Financial> findFinancialsByMonthPm(PerformanceAssign entity) {
		Criteria criteria = billOptionService.getEntityDao().createCriteria();
		criteria.setProjection(Projections.groupProperty("financial"));
		criteria.createCriteria("paShopMonthDetail").createCriteria("performanceAssignShopDetail").add(Restrictions.eq("performanceAssign", entity));
		criteria.createCriteria("treaty").add(Restrictions.or(Restrictions.isNull("collectionWay"), Restrictions.eq("collectionWay", "0")));
		criteria.createCriteria("financial").addOrder(Order.desc("billing"));
		
		return criteria.list();
	}

	/**
	 * 查找这次绩效所关联的金融机构,按多个月份 收，，季度，，半年。。
	 * 
	 * @param entity
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public List<Financial> findFinancialsByManyMonthPm(PerformanceAssign entity) {
		Criteria criteria = billOptionService.getEntityDao().createCriteria();
		criteria.setProjection(Projections.groupProperty("financial"));
		criteria.createCriteria("paShopMonthDetail").createCriteria("performanceAssignShopDetail").add(Restrictions.eq("performanceAssign", entity));
		criteria.createCriteria("treaty").add(Restrictions.and(Restrictions.isNotNull("collectionWay"), Restrictions.ne("collectionWay", "0")));
		criteria.createCriteria("financial").addOrder(Order.desc("billing"));
		
		return criteria.list();
	}
	
	/**
	 * 查找这次绩效所关联的 月份,按月份收  
	 * @param entity
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public List<String> findMonthsByMonthPm(PerformanceAssign entity) { 
//		Criteria criteria = this.getEntityDao().createCriteria();
//		criteria.setProjection(Projections.groupProperty("monthDate"));
//		criteria.createCriteria("performanceAssignShopDetail").add(Restrictions.eq("performanceAssign", entity));
		
		Criteria criteria = billOptionService.getEntityDao().createCriteria();
		criteria.setProjection(Projections.groupProperty("month"));
		criteria.createCriteria("paShopMonthDetail").createCriteria("performanceAssignShopDetail").add(Restrictions.eq("performanceAssign", entity));
		criteria.createCriteria("treaty").add(Restrictions.or(Restrictions.isNull("collectionWay"), Restrictions.eq("collectionWay", "0")));
		criteria.addOrder(Order.desc("month"));
		return criteria.list();
	}

	/**
	 * 查找这次绩效所关联的 月份,按月份收  
	 * @param entity
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public List<String> findFinancialMonthsByMonthPm(PerformanceAssign entity, Financial financial) { 
//		Criteria criteria = this.getEntityDao().createCriteria();
//		criteria.setProjection(Projections.groupProperty("monthDate"));
//		criteria.createCriteria("performanceAssignShopDetail").add(Restrictions.eq("performanceAssign", entity));
		
		Criteria criteria = billOptionService.getEntityDao().createCriteria();
		criteria.setProjection(Projections.groupProperty("month"));
		criteria.add(Restrictions.eq("financial", financial));
		criteria.createCriteria("paShopMonthDetail").createCriteria("performanceAssignShopDetail").add(Restrictions.eq("performanceAssign", entity));
		criteria.createCriteria("treaty").add(Restrictions.and(Restrictions.isNotNull("collectionWay"), Restrictions.ne("collectionWay", "0")));
		criteria.addOrder(Order.asc("month"));
		return criteria.list();
	}
	
	@SuppressWarnings("unchecked")
	public List<PAShopMonthDetail> findByMonth(String month,
			PerformanceAssign entity) {
		Criteria criteria = this.getEntityDao().createCriteria();
		criteria.add(Restrictions.eq("monthDate", month));
		Criteria shopDetailCriteria = criteria.createCriteria("performanceAssignShopDetail");
		
		shopDetailCriteria.add(Restrictions.eq("performanceAssign", entity));
		Criteria shopCriteria = shopDetailCriteria.createCriteria("shop");
		
		shopCriteria.addOrder(Order.desc("area"));
		shopCriteria.addOrder(Order.asc("shopMark"));
		
		return criteria.list();
	}

	/** 
	 * 获取 按多个月份收取的金融机构关联的店铺。
	 * 
	 * @param financial
	 * @param months
	 * @param entity
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public List<PerformanceAssignShopDetail> findByFinancialMonths(Financial financial,
			List<String> months, PerformanceAssign entity) {
		Criteria criteria = this.getEntityDao().createCriteria();
		criteria.setProjection(Projections.groupProperty("performanceAssignShopDetail"));
		Criteria shopDetailCriteria = criteria.createCriteria("performanceAssignShopDetail");
		shopDetailCriteria.add(Restrictions.eq("performanceAssign", entity));
		Criteria shopCriteria = shopDetailCriteria.createCriteria("shop");
		shopCriteria.addOrder(Order.desc("area"));
		shopCriteria.addOrder(Order.asc("shopMark"));
		
		Criteria billOptionCriteria = criteria.createCriteria("billOptions", JoinFragment.RIGHT_OUTER_JOIN);
		billOptionCriteria.add(Restrictions.eq("financial", financial));
		billOptionCriteria.add(Restrictions.in("month", months));
		billOptionCriteria.createCriteria("treaty").add(Restrictions.and(Restrictions.isNotNull("collectionWay"), Restrictions.ne("collectionWay", "0")));
		
		return criteria.list();
	}

	@SuppressWarnings("unchecked")
	public String getAssignUserNamesByFinancialIdMonths(Long financialId,
			List<String> months, PerformanceAssignShopDetail shopDetail) {
		if(months == null || months.size() < 1){
			return "";
		}
		
		Criteria criteria = assignUserService.getEntityDao().createCriteria();
		criteria.setProjection(Projections.groupProperty("user"));
		criteria.add(Restrictions.eq("postType", PostType.Shop));
		
		Criteria shopCriteria = criteria.createCriteria("paShopMonthDetail");
		shopCriteria.add(Restrictions.eq("performanceAssignShopDetail", shopDetail));
		shopCriteria.createCriteria("billOptions").add(Restrictions.eq("financial.id", financialId));
		shopCriteria.add(Restrictions.in("monthDate", months));
		
		List<User> users = criteria.list();
		return users != null ? ReflectionUtils.convertElementPropertyToString(users, "realName", ","): "";
	}
	
}
